/*
* Copyright 2015 2dfire.com All right reserved. This software is the
* confidential and proprietary information of 2dfire.com ("Confidential
* Information"). You shall not disclose such Confidential Information and shall
* use it only in accordance with the terms of the license agreement you entered
* into with 2dfire.com.
*/
package com.dfire.mtm.taskNode.impl;

import com.dfire.mtm.constant.TaskLife;
import com.dfire.mtm.executor.MtmRunnable;
import com.dfire.mtm.taskNode.AbstractTaskNode;
import com.dfire.mtm.taskNode.TaskData;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;

/**
 * 阻塞式任务节点，
 * 只有当父节点某任务全都结束时才会执行
 * @author guipi
 * @description
 * @date 2018/10/23
 * ----------重大变更记录------------
 */
public class BlockTaskNode extends AbstractTaskNode {

    public BlockTaskNode(String name) {
        this.name = name;
    }

    public BlockTaskNode(String name, MtmRunnable mtmRunnable, ExecutorService executorService) {
        this.name = name;
        this.mtmRunnable = mtmRunnable;
        this.mtmRunnable.setTaskNode(this);
        this.executor = executorService;
    }

    @Override
    public void execute() {
        while (true){
            if(executor.isShutdown()){
                return;
            }
            if(mtmRunnable==null){
                throw new NullPointerException("runnable is null");
            }
            if (!getAnyTaskFinished().isEmpty()){
                executor.execute(mtmRunnable);
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private Set<String> getAnyTaskFinished(){
        Set<String> finishedTask = new HashSet<>();
        for(String node:parentTaskStatus.keySet()){
            ConcurrentHashMap<String,TaskLife> taskMap = parentTaskStatus.get(node);
            for(String task:taskMap.keySet()){
                if(taskMap.get(task)==TaskLife.FINISH){
                    finishedTask.add(task);
                } else if(finishedTask.contains(task)){
                    finishedTask.remove(task);
                }
            }
        }
        return finishedTask;
    }

    @Override
    public <T> TaskData<T> nextData() {
        Set<String> finishedTask = getAnyTaskFinished();
        if(finishedTask.isEmpty()){
            return null;
        }
        for(String task:finishedTask){
            T t = getData(task);
            if(t!=null){
                return new TaskData<>(task,t);
            } else {
                tryCleanTask(task);
            }
        }

        return null;
    }

    @Override
    public <T> T getData(String task) {
        Set<String> finishedTask = getAnyTaskFinished();
        if(finishedTask.isEmpty() || !finishedTask.contains(task)){
            return null;
        }
        T t = super.getData(task);
        return t;
    }
}
